﻿using System;
using System.Data;
using System.Data.SqlClient;
using System.Text;

/// <summary>
/// Métodos para que se puedan obtener los datos del ObjectDataSource Search
/// </summary>
public class SearchODS
{
    // Regresa el resultado de la búsqueda
    public DataTable SearchResult(String SearchString, String SearchType, Int32 startRowIndex, Int32 maximumRows)
    {
        if (String.IsNullOrEmpty(SearchString) || String.IsNullOrEmpty(SearchType))
        {
            SearchString = "-1";
            SearchType = "Nothing";
        }

        String TypeOfSearch = this.TypeOfSearch(SearchType);

        startRowIndex = startRowIndex + 1;
        Int32 lastRow = startRowIndex + (maximumRows - 1);
        Int32 numberOfParameters = 0;

        String selectQueryString;
        String[] parametersNameArray = new string[] { };
        
        if (String.Equals(TypeOfSearch, "NombreAlumno"))
        {
            TimesLikeOperator(ref SearchString, ref parametersNameArray, ref numberOfParameters);
            selectQueryString =
                "SELECT * FROM (SELECT Solicitud.Folio, Solicitud.Matricula, " +
                "Alumnos.Nombre + ' ' + Alumnos.Apellido AS [NombreAlumno], " +
                "CONVERT(VARCHAR(25), Solicitud.Solicitud_Fecha, 0) AS [FechaEnviada], " +
                "ROW_NUMBER() OVER (ORDER BY Solicitud.TimeStamp_FechaCreacion DESC) AS [RowNumber] " +
                "FROM Alumnos, Solicitud WHERE Solicitud.Matricula = Alumnos.Matricula AND " +
                "(" + SearchString + ")) AS TEMP WHERE [RowNumber] BETWEEN @startRowIndex AND @lastRow;";
        }
        else
        {
            selectQueryString =
                "SELECT * FROM (SELECT Solicitud.Folio, Solicitud.Matricula, " +
                "Alumnos.Nombre + ' ' + Alumnos.Apellido AS [NombreAlumno], " +
                "CONVERT(VARCHAR(25), Solicitud.Solicitud_Fecha, 0) AS [FechaEnviada], " +
                "ROW_NUMBER() OVER (ORDER BY Solicitud.TimeStamp_FechaCreacion DESC) AS [RowNumber] " +
                "FROM Alumnos, Solicitud WHERE Solicitud.Matricula = Alumnos.Matricula AND " + TypeOfSearch +
                " = @SearchString) AS TEMP WHERE [RowNumber] BETWEEN @startRowIndex AND @lastRow;";
        }


        DataTable dataTableObject = new DataTable();
        using (SqlCommand selectQueryCommand = new SqlCommand(selectQueryString))
        {
            Int32 inItsCaseFolio;

            // Cuando no se regresará ningún resultado (por ejemplo, en el caso de que busquen un
            // nombre con 2 caracteres o menos.
            if (String.Equals(SearchString, "(Alumnos.Nombre LIKE @TheresNoResult)"))
            {
                selectQueryCommand.Parameters.Add("@TheresNoResult", SqlDbType.VarChar, 200);
                selectQueryCommand.Parameters["@TheresNoResult"].Value = "TheresNoResult%";
            }
                // Caso en que la búsqueda sea un folio
            else if (String.Equals(SearchType, "Folio"))
            {
                selectQueryCommand.Parameters.Add(!Int32.TryParse(SearchString, out inItsCaseFolio)
                                                      ? new SqlParameter("@SearchString", -1)
                                                      : new SqlParameter("@SearchString", inItsCaseFolio));
            }
                // Para el caso que sea NombreAlumno, se tiene que modificar el parámetro @SearchString
                // para que acepte el comando LIKE
            else if (String.Equals(SearchType, "NombreAlumno"))
            {
                for (int i = 0; i < numberOfParameters; i++)
                {
                    selectQueryCommand.Parameters.Add("@Param" + parametersNameArray[i] + i.ToString(), SqlDbType.VarChar, 200);
                    selectQueryCommand.Parameters["@Param" + parametersNameArray[i] + i.ToString()].Value = parametersNameArray[i] + "%";
                }
            }
                // Caso para buscar matrícula
            else
            {
                selectQueryCommand.Parameters.Add(new SqlParameter("@SearchString", SearchString));
            }

            selectQueryCommand.Parameters.Add(new SqlParameter("@startRowIndex", startRowIndex));
            selectQueryCommand.Parameters.Add(new SqlParameter("@lastRow", lastRow));

            DatabaseConnection dbCon = new DatabaseConnection();
            using (SqlDataAdapter dataAdapter = dbCon.DataAdapter(selectQueryCommand))
            {
                dataAdapter.Fill(dataTableObject);
            }
            dbCon.CloseConnection();
        }
        return dataTableObject;
    }


    // Regresa el número de rows que existen en el el query que se desea consultar
    public Int32 CountRows(String SearchString, String SearchType)
    {
        if (String.IsNullOrEmpty(SearchString) || String.IsNullOrEmpty(SearchType))
        {
            SearchString = "Nothing";
            SearchType = "Nothing";
        }

        Int32 numeroRows;
        Int32 numberOfParameters = 0;

        String TypeOfSearch = this.TypeOfSearch(SearchType);
        String SelectCountString;
        String[] parametersNameArray = new string[] {};

        if (String.Equals(TypeOfSearch, "NombreAlumno"))
        {
            TimesLikeOperator(ref SearchString, ref parametersNameArray, ref numberOfParameters);
            SelectCountString = "SELECT COUNT(*) FROM Solicitud, Alumnos " +
                                "WHERE Solicitud.Matricula = Alumnos.Matricula AND " +
                                "(" + SearchString + ") AND Solicitud.Solicitud_Enviada = 1";
        } 
        else
        {
            SelectCountString = "SELECT COUNT(*) FROM Solicitud, Alumnos " +
                                "WHERE Solicitud.Matricula = Alumnos.Matricula AND " + TypeOfSearch + " = @SearchString AND Solicitud.Solicitud_Enviada = 1";
        }

        using (SqlCommand SelectCount = new SqlCommand(SelectCountString))
        {
            // Cuando no se regresará ningún resultado (por ejemplo, en el caso de que busquen un
            // nombre con 2 caracteres o menos.
            if (String.Equals(SearchString, "(Alumnos.Nombre LIKE @TheresNoResult)"))
            {
                SelectCount.Parameters.Add("@TheresNoResult", SqlDbType.VarChar, 200);
                SelectCount.Parameters["@TheresNoResult"].Value = "TheresNoResult%";
            }
            // Caso en que la búsqueda sea un folio
            else if (String.Equals(SearchType, "Folio"))
            {
                Int32 inItsCaseFolio;
                SelectCount.Parameters.Add(!Int32.TryParse(SearchString, out inItsCaseFolio)
                                               ? new SqlParameter("@SearchString", -1)
                                               : new SqlParameter("@SearchString", inItsCaseFolio));
            }
                // Para el caso que sea NombreAlumno, se tiene que modificar el parámetro @SearchString
                // para que acepte el comando LIKE
            else if (String.Equals(SearchType, "NombreAlumno"))
            {
                for (int i = 0; i < numberOfParameters; i++)
                {
                    SelectCount.Parameters.Add("@Param" + parametersNameArray[i] + i.ToString(), SqlDbType.VarChar, 200);
                    SelectCount.Parameters["@Param" + parametersNameArray[i] + i.ToString()].Value = parametersNameArray[i] + "%";
                }
            }
            // Caso para buscar matrícula
            else
            {
                SelectCount.Parameters.Add(new SqlParameter("@SearchString", SearchString));
            }

            DatabaseConnection dbCon = new DatabaseConnection();
            numeroRows = dbCon.ExecuteScalar(SelectCount);
            dbCon.CloseConnection();
        }
        return numeroRows;
    }



    /* Determina sobre qué columna se va a realizar la búsqueda dependiendo
     * del SearchType. Se tiene que hacer de esta manera porque mediante un nuevo
     * parámetro con el SqlCommander no es posible referenciar nombre de columnas.
     */

    public String TypeOfSearch(String SearchType)
    {
        String Type;
        if (String.Equals(SearchType, "Matricula"))
        {
            Type = "Alumnos.Matricula";
        }
        else if (String.Equals(SearchType, "NombreAlumno"))
        {
            Type = "NombreAlumno";
        }
        else if (String.Equals(SearchType, "Folio"))
        {
            Type = "Solicitud.Folio";
        }
        else
        {
            Type = "-1";
        }
        return Type;
    }


    /* Determina el número de parámetros que se van a generar para la búsqueda.
     * Por cada palabra mayor de 2 letras, se generará un parámetro para Alumnos.Nombre
     * y otro para Alumnos.Apellidos, para tener un nivel de búsqueda amplia.
     * param SearchString por referencia, es el String que se incluye en el Query.
     * param parametersNameArray[] por referencia, son los nombres que se incluirán en el
     *       condicional LIKE por cada parámetro generado en el Query.
     * param numberOfParams por referencia es el número de parámetros que se generaron.
     */
    public static String TimesLikeOperator(ref String SearchString, ref String[] parametersNameArray,
                                           ref Int32 numberOfParams)
    {
        if (String.IsNullOrEmpty(SearchString) || SearchString.Length <= 2)
        {
            return SearchString = "(Alumnos.Nombre LIKE @TheresNoResult)";
        }

        char[] delimiters = {' ', ','};
        String[] splitedString = SearchString.Split(delimiters, StringSplitOptions.RemoveEmptyEntries);

        SearchString = String.Empty;
        String usedParams = String.Empty;

        // Se genera el String de LIKE
        for (int i = 0; i < splitedString.Length; i++)
        {
            if (splitedString[i].Length > 2 && (i + 1) < splitedString.Length)
            {
                usedParams += splitedString[i] + ",";
                SearchString += "Alumnos.Nombre LIKE @Param" + splitedString[i] + numberOfParams.ToString() +
                                " OR Alumnos.Apellido LIKE @Param" + splitedString[i] + numberOfParams.ToString() +
                                " OR ";
                numberOfParams++;
            }
            else if (splitedString[i].Length > 2 && (i + 1) >= splitedString.Length)
            {
                usedParams += splitedString[i] + ",";
                SearchString += "Alumnos.Nombre LIKE @Param" + splitedString[i] + numberOfParams.ToString() +
                                " OR Alumnos.Apellido LIKE @Param" + splitedString[i] + numberOfParams.ToString();
                numberOfParams++;
            }
        }

        // Se Obtienen los nombres de los parámetros que se usarán en el builder 
        // de parámetros del SqlCommander String
        parametersNameArray = usedParams.Split(delimiters, StringSplitOptions.RemoveEmptyEntries);

        return SearchString;
    }

}
